home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 011 / ldres.arc / LDRES.DOC < prev   
Text File  |  1987-01-06  |  8KB  |  175 lines

  1. Eric Gans
  2. French Dep't UCLA
  3. Los Angeles, CA 90024
  4.  
  5.                          LDRES.DOC v1.0
  6.                             01/05/87
  7.  
  8.      It's  laborious but fairly straightforward to write  memory-
  9. resident  programs in assembly language.   You know the  size  of 
  10. your program;  you know how much memory it needs;  you know where 
  11. to  enter it from your interrupt routine.   All this changes  for 
  12. the  worse when you work in a higher-level  language.   Compilers 
  13. don't  come with a "makeres" function that rearranges their  code 
  14. for this purpose.   Even a language as flexible as C requires you 
  15. to handle most of the residency process through assembly-language 
  16. modules.
  17.  
  18.      LDRES is a tool for MS/PC-DOS 2+ that simplifies the process 
  19. of  turning  a utility written in C,  Pascal or whatever  into  a 
  20. resident program.   It requires a few fixups from the programmer, 
  21. but if you know what you're doing, the extra work is minimal.
  22.  
  23.      What LDRES does
  24.  
  25.      LDRES  takes  a  COM file as input,  and tacks a  couple  of 
  26. modules  on  the end of it,  including an interrupt (9)  routine.  
  27. When  the  modified program is first run,  control  jumps  to  an 
  28. initialization  module  that  sets up the interrupt  routine  and 
  29. leaves  the program memory-resident.   As expected by COM  files, 
  30. the interrupt routine sets all segment registers to the CS  value 
  31. before passing control to your program.  On return, all registers 
  32. are restored and an IRET is executed.
  33.  
  34.      The  command-line  "m"  switch allows  you  to  specify  the 
  35. additional memory needed for stack & heap functions (and to avoid 
  36. "insufficient  memory" errors at run-time).   The memory is added 
  37. below the interrupt routine; you must request enough to make sure 
  38. this routine is not overwritten by your compiler's initialization 
  39. procedures.   The default is 100h bytes for a minimal  stack;  on 
  40. program  entry the stack pointer is set to the top of this  area, 
  41. just  below the interrupt routine.   (Fourteen bytes are added to 
  42. this figure by registers pushed by the interrupt routine.)  Don't 
  43. forget that even if your program  doesn't use the stack,   one is 
  44. needed for the interrupts that will occur during its execution.
  45.  
  46.      So  that  your  program can check to see if  it  is  already 
  47. memory-resident  (and  not load a second time),  LDRES sets up  a 
  48. dummy  interrupt  address  into which it  places  the  first  two 
  49. letters  of  the filename.   The default setting for this is  int 
  50. 7eh;  it can be changed by using the "i" switch.  
  51.  
  52.      LDRES  allows  you to remove your program from  memory  when 
  53. already  resident  by entering "fn /r" on the DOS  command  line.  
  54. This  should  generally only be done if your program is the  last 
  55. loaded, since interrupt 9 control is passed back to the preceding 
  56. program.
  57.  
  58.      LDRES  returns to you with a "program return address"  which 
  59. you should note down. You then patch the exit function(s) of your 
  60. program to JMP to this address, and presto, your program has been 
  61. converted  into  a memory-resident utility that will  be  invoked 
  62. whenever a certain key combination is pressed.  
  63.  
  64.      HOWEVER...
  65.  
  66.      You  may have to make a few other  changes.   The  following 
  67. refers  to my own experience with the Lattice C compiler  (v3.1); 
  68. other compilers may pose other problems.
  69.  
  70.      1.  For  one thing,  you can't use standard DOS input/output 
  71. functions.  You'll have to write assembly-language routines using 
  72. interrupts  16h and 10h.   Writing to the screen buffer  is  easy 
  73. enough,  but getting input forces you to do your own editing.   I 
  74. won't go into the matters of windows,  saving the user's  screen, 
  75. etc.   Some  other  DOS functions won't work either;  it took  me 
  76. several days to discover that the innocent-appearing function 30h 
  77. (Get DOS version) sends memory-resident programs out to lunch.
  78.  
  79.      2.  You  will have to disable the memory-management function 
  80. of  your  compiler that wants to return all extra memory  to  DOS 
  81. when  your  program runs.   The program doesn't  know  about  the 
  82. interrupt  routine sitting on top of it.   Since your program  is 
  83. already resident,  i.e.,  uses a fixed memory space, the simplest 
  84. thing is just to kill (NOP out) such functions.  Look out for DOS 
  85. function 4Ah (or maybe 49h) here.
  86.  
  87.      3. Compilers expect your program to run once and then return 
  88. to DOS.  You may have to reinitialize data areas that are changed 
  89. by  the  program,  or better still,  find a way of  keeping  them 
  90. unchanged.   Routines  to  get the  environment  or  command-line 
  91. parameters  are unnecessary in a resident program--if you need to 
  92. look  at  the  environment,  it's  better to see  a  fresh  copy.  
  93. Lattice  C kindly gives you the source for  their  initialization 
  94. module  (C.ASM),  so  it's  not too hard to modify  it  for  this 
  95. purpose;  most  languages  build this function directly into  the 
  96. compiler, so you may have to patch your COM file.  
  97.  
  98.      If you write in C, be sure to end your program with _exit(), 
  99. not  exit().   The  latter  closes all  file  handles,  including 
  100. standard  input & output,  expecting DOS to  reopen  them.   This 
  101. would  be disastrous if you ran your memory-resident program from 
  102. within another application.   Of course the _exit() function must 
  103. be  patched with a JMP to the program return address in place  of 
  104. its  return to DOS.   The _tinymain() function will do  this  for 
  105. you, while saving time by not opening stdin, stderr and the like.
  106.  
  107.      Running LDRES
  108.  
  109.      Format: ldres [\path\]fn.com [/snn /cnn /inn /mnnnn /wblabl]
  110.  
  111. The switches may be used in any order (enter all numbers in HEX):
  112.  
  113. /snn = BIOS shift byte value.   The program default for this byte 
  114. is  8,  meaning that the Alt key is pressed.   The shift byte  is 
  115. located at 0000:0417h.  If you don't have documentation, XRAY.COM 
  116. will display these values on your screen.
  117.  
  118. /cnn  = scan code.   This is for the key you press along with the 
  119. shift(s).  The default is 35h,  or 53,  the "/" key.  (Be careful 
  120. not to enter the scan code in decimal.)
  121.  
  122. /inn = dummy interrupt number.  This comes set to 7eh, and can be 
  123. changed  to anything you like;  just be sure not to use an active 
  124. interrupt.
  125.  
  126. /mnnnn = additional bytes of memory.  Unless you are converting a 
  127. small assembly-language program, you should go beyond the default 
  128. of 100h (=256 bytes);  the minimal figure for Lattice C is around 
  129. 500h = 1280 bytes.  
  130.  
  131. /wblabla = message to be added to the filename on loading.   This 
  132. is a string of ASCII characters (no cr's,  linefeeds, tabs) up to 
  133. a maximum of 47.   The string must be terminated by a '$'.   When 
  134. your  program is loaded into memory,  it will output  "Installing 
  135. fn.com[your message]<CR>". Be sure to include a space if you want 
  136. one  after  the filename.   If you want the filename  in  capital 
  137. letters, enter it that way on the LDRES command line.
  138.  
  139.      A Sample Session with LDRES
  140.  
  141.      This  recounts  my  experience in  creating  MCALC.COM,  the 
  142. program for which I wrote LDRES in the first place.
  143.  
  144.      1.  Write the higher-level program (e.g.  in C),  being sure 
  145. to get the I/O right.  Use _TINYMAIN, and exit with _exit().
  146.  
  147.      2.  Fix  up  the load module C.ASM  to  eliminate:  (a)  the 
  148. rbrk()   memory-management  routine  (function   4A);   (b)   the 
  149. environment/command-line   routines;   (c)  sticky  calls,   like 
  150. function 30 mentioned above.
  151.  
  152.      3.  Compile  & link using the modified load module (I called 
  153. this CRES.OBJ).
  154.  
  155.      4.   Run  LDRES  with  the  COM  file  and  the  appropriate 
  156. parameters.
  157.  
  158.      5.   Using  a  debugger,   kill  all  remaining  troublesome 
  159. functions  and set a JMP at exit to the "program return  address" 
  160. output by LDRES.
  161.  
  162.      6.  Put  the program name in your AUTOEXEC file,  reset  the 
  163. computer and pray.
  164.  
  165.      7. Here you have the advantage over me of not having to look 
  166. for bugs in LDRES if something goes wrong.  If your program hangs 
  167. the  computer,  the problem is probably in items (1) or  (2),  so 
  168. loop until done.
  169.  
  170.      A  final  word  of  advice;   try  out  LDRES  first  on  an 
  171. short  experimental program to learn what tricks you'll  have  to 
  172. play on your compiler in order to turn its product into a memory-
  173. resident application.   Good luck,  and keep your finger near the 
  174. big red switch!
  175.